package com.jnc.rest.util;

import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Auther: jjn
 * @Date: 2018/8/11
 * @Description: 类型转换器工具类
 */
public class ConvertUtil {

    public static final String UTF_8 = "UTF-8";
    public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
    private static final String REGEX_TYPE = "_(\\w)";
    private static final String UNDER_LINE = "_";

    /**
     * 转换为字符串
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @param defaultValue
     * @return
     */
    public static String toStr(Object value, String defaultValue){
        if(null == value){
            return defaultValue;
        }
        if(value instanceof String){
            return (String) value;
        }
        return value.toString();
    }

    /**
     * 转换为字符串
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @return
     */
    public static String toStr(Object value){
        return toStr(value, null);
    }

    /**
     * 转换字符(多字符的字符串，返回第一个字符)
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @param defaultValue
     * @return
     */
    public static Character toChar(Object value, Character defaultValue){
        if(null == value){
            return defaultValue;
        }
        if(value instanceof Character){
            return (Character) value;
        }
        final String valueStr = toStr(value);
        return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0);
    }

    /**
     * 转换字符(多字符的字符串，返回第一个字符)
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @return
     */
    public static Character toChar(Object value){
        return toChar(value, null);
    }

    /**
     * 转换为byte
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @param defaultValue
     * @return
     */
    public static Byte toByte(Object value, Byte defaultValue){
        if(null == value){
            return defaultValue;
        }
        if(value instanceof Byte){
            return (Byte) value;
        }
        if(value instanceof Number){
            return ((Number) value).byteValue();
        }
        final String valueStr = toStr(value);
        if(StringUtils.isEmpty(valueStr)){
            return defaultValue;
        }
        try{
            return Byte.parseByte(valueStr);
        }catch (Exception e){
            return defaultValue;
        }
    }

    /**
     * 转换为byte
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @return
     */
    public static Byte toByte(Object value){
        return toByte(value, null);
    }

    /**
     * 转换为Short
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @param defaultValue
     * @return
     */
    public static Short toShort(Object value, Short defaultValue){
        if(null == value){
            return defaultValue;
        }
        if(value instanceof Short){
            return (Short) value;
        }
        if(value instanceof Number){
            return ((Number) value).shortValue();
        }
        final String valueStr = toStr(value);
        if(StringUtils.isEmpty(valueStr)){
            return defaultValue;
        }
        try{
            return Short.parseShort(valueStr.trim());
        }catch (Exception e){
            return defaultValue;
        }
    }

    /**
     * 转换为Short
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @return
     */
    public static Short toShort(Object value){
        return toShort(value, null);
    }

    /**
     * 转换为Number
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @param defaultValue
     * @return
     */
    public static Number toNumber(Object value, Number defaultValue){
        if(null == value){
            return defaultValue;
        }
        if(value instanceof Number){
            return (Number) value;
        }
        final String valueStr = toStr(value);
        if(StringUtils.isEmpty(valueStr)){
            return defaultValue;
        }
        try{
            return NumberFormat.getInstance().parse(valueStr);
        }catch (Exception e){
            return defaultValue;
        }
    }

    /**
     * 转换为Number
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @return
     */
    public static Number toNumber(Object value){
        return toNumber(value, null);
    }

    /**
     * 转换为Integer
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @param defaultValue
     * @return
     */
    public static Integer toInt(Object value, Integer defaultValue){
        if(null == value){
            return defaultValue;
        }
        if(value instanceof Integer){
            return (Integer) value;
        }
        if(value instanceof Number){
            return ((Number) value).intValue();
        }
        final String valueStr = toStr(value);
        if(StringUtils.isEmpty(valueStr)){
            return defaultValue;
        }
        try{
            return Integer.parseInt(valueStr.trim());
        }catch (Exception e){
            return defaultValue;
        }
    }

    /**
     * 转换为Integer
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @return
     */
    public static Integer toInt(Object value){
        return toInt(value, null);
    }

    /**
     * 转换为Long
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @param defaultValue
     * @return
     */
    public static Long toLong(Object value, Long defaultValue){
        if (value == null){
            return defaultValue;
        }
        if (value instanceof Long){
            return (Long) value;
        }
        if (value instanceof Number){
            return ((Number) value).longValue();
        }
        final String valueStr = toStr(value);
        if (StringUtils.isEmpty(valueStr)){
            return defaultValue;
        }
        try{
            // 支持科学计数法
            return new BigDecimal(valueStr.trim()).longValue();
        }catch (Exception e){
            return defaultValue;
        }
    }

    /**
     * 转换为Long
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @return
     */
    public static Long toLong(Object value){
        return toLong(value, null);
    }

    /**
     * 转换为Double
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @param defaultValue
     * @return
     */
    public static Double toDouble(Object value, Double defaultValue){
        if (value == null){
            return defaultValue;
        }
        if (value instanceof Double){
            return (Double) value;
        }
        if (value instanceof Number){
            return ((Number) value).doubleValue();
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr)){
            return defaultValue;
        }
        try{
            // 支持科学计数法
            return new BigDecimal(valueStr.trim()).doubleValue();
        }catch (Exception e){
            return defaultValue;
        }
    }

    /**
     * 转换为Double
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @return
     */
    public static Double toDouble(Object value){
        return toDouble(value, null);
    }

    /**
     * 转换为Float
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @param defaultValue
     * @return
     */
    public static Float toFloat(Object value, Float defaultValue){
        if (value == null){
            return defaultValue;
        }
        if (value instanceof Float){
            return (Float) value;
        }
        if (value instanceof Number){
            return ((Number) value).floatValue();
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr)){
            return defaultValue;
        }
        try{
            return Float.parseFloat(valueStr.trim());
        }catch (Exception e){
            return defaultValue;
        }
    }

    /**
     * 转换为Float
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @return
     */
    public static Float toFloat(Object value){
        return toFloat(value, null);
    }

    /**
     * 转换为BigDecimal
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @param defaultValue
     * @return
     */
    public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue){
        if (value == null){
            return defaultValue;
        }
        if (value instanceof BigDecimal){
            return (BigDecimal) value;
        }
        if (value instanceof Long){
            return new BigDecimal((Long) value);
        }
        if (value instanceof Double){
            return new BigDecimal((Double) value);
        }
        if (value instanceof Integer){
            return new BigDecimal((Integer) value);
        }
        final String valueStr = toStr(value, null);
        if (StringUtils.isEmpty(valueStr)){
            return defaultValue;
        }
        try{
            return new BigDecimal(valueStr);
        }catch (Exception e){
            return defaultValue;
        }
    }

    /**
     * 转换为BigDecimal
     * (1)、如果给定的值为null，或者转换失败，返回默认值；转换失败不会报错
     * @param value
     * @return
     */
    public static BigDecimal toBigDecimal(Object value){
        return toBigDecimal(value, null);
    }

    /**
     * 转换为Integer数组
     * @param split 分隔符
     * @param str
     * @return
     */
    public static Integer[] toIntArray(String split, String str){
        if(StringUtils.isEmpty(str)){
            return new Integer[]{};
        }
        String[] arr = str.split(split);
        final Integer[] ints = new Integer[arr.length];
        for (int i = 0; i < arr.length; i++){
            final Integer v = toInt(arr[i]);
            ints[i] = v;
        }
        return ints;
    }

    /**
     * 转换为Integer数组(分隔符默认是逗号)
     * @param str
     * @return
     */
    public static Integer[] toIntArray(String str){
        return toIntArray(",", str);
    }


    public static List<Integer> toIntList(String str){
        return Arrays.asList(toIntArray(str));
    }

    /**
     * 转换为Long数组
     * @param split
     * @param str
     * @return
     */
    public static Long[] toLongArray(String split, String str){
        if(StringUtils.isEmpty(str)){
            return new Long[]{};
        }
        String[] arr = str.split(split);
        final Long[] longs = new Long[arr.length];
        for (int i = 0; i < arr.length; i++){
            final Long v = toLong(arr[i]);
            longs[i] = v;
        }
        return longs;
    }

    /**
     * 转换为Long数组(分隔符默认是逗号)
     * @param str
     * @return
     */
    public static Long[] toLongArray(String str){
        return toLongArray(",", str);
    }

    public static List<Long> toLongList(String str){
        return Arrays.asList(toLongArray(str));
    }

    /**
     * 转换为String数组
     * @param split
     * @param str
     * @return
     */
    public static String[] toStrArray(String split, String str){
        if(null == str){
            return new String[]{};
        }
        return str.split(split);
    }

    /**
     * 转换为String数组(分隔符默认是逗号)
     * @param str
     * @return
     */
    public static String[] toStrArray(String str){
        return toStrArray(",", str);
    }

    public static List<String> toStrList(String str){
        return Arrays.asList(toStrArray(str));
    }

    /**
     * 将对象转字符串(使用UTF-8字符集)
     * @param obj
     * @return
     */
    public static String utf8Str(Object obj){
        return str(obj, CHARSET_UTF_8);
    }

    /**
     * 将对象转字符串
     * @param obj
     * @param charsetName
     * @return
     */
    public static String str(Object obj, String charsetName){
        return str(obj, Charset.forName(charsetName));
    }

    /**
     * 将对象转字符串
     * @param obj
     * @param charset
     * @return
     */
    public static String str(Object obj, Charset charset){
        if(null == obj){
            return null;
        }
        if(obj instanceof String){
            return (String) obj;
        }else if(obj instanceof byte[] || obj instanceof Byte[]){
            return str((Byte[]) obj, charset);
        }else if(obj instanceof ByteBuffer){
            return str((ByteBuffer) obj, charset);
        }
        return obj.toString();
    }

    /**
     * 字节数组转字符串
     * @param bytes
     * @param charsetName
     * @return
     */
    public static String str(byte[] bytes, String charsetName){
        return str(bytes, StringUtils.isEmpty(charsetName) ? Charset.defaultCharset() : Charset.forName(charsetName));
    }

    /**
     * 字节数组转字符串
     * @param data
     * @param charset
     * @return
     */
    public static String str(byte[] data, Charset charset){
        if(null == data){
            return null;
        }
        if(null == charset){
            return new String(data);
        }
        return new String(data, charset);
    }

    /**
     * byteBuffer转字符串
     * @param data
     * @param charsetName
     * @return
     */
    public static String str(ByteBuffer data, String charsetName){
        if(null == data){
            return null;
        }
        return str(data, Charset.forName(charsetName));
    }

    /**
     * byteBuffer转字符串
     * @param data
     * @param charset
     * @return
     */
    public static String str(ByteBuffer data, Charset charset){
        if(null == charset){
            charset = Charset.defaultCharset();
        }
        return charset.decode(data).toString();
    }


    /**
     * 驼峰命名转下划线命名
     * @param str
     * @return
     */
    public static String camelToUnderline(String str) {
        if (str == null || str.trim().isEmpty()){
            return "";
        }

        int len = str.length();
        StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            char c = str.charAt(i);
            if (Character.isUpperCase(c)){
                sb.append(UNDER_LINE);
                sb.append(Character.toLowerCase(c));
            }else{
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 下划线字符串转驼峰命名(大写先转小写，首字母小写)
     * @param str
     * @return
     */
    public static String toLowerCamelCase(String str){
        if(null == str){
            return null;
        }
        str = str.toLowerCase();
        final StringBuffer sb = new StringBuffer();
        Pattern p = Pattern.compile(REGEX_TYPE);
        Matcher m = p.matcher(str);
        while(m.find()){
            m.appendReplacement(sb, m.group(1).toUpperCase());
        }
        m.appendTail(sb);
        return sb.toString();
    }

    /**
     * 下划线字符串转驼峰命名(首字母大写)
     * @param str
     * @return
     */
    public static String toUpperCamelCase(String str){
        StringBuilder result = new StringBuilder();
        // 快速检查
        if (str == null || str.isEmpty()){
            // 没必要转换
            return "";
        }else if (!str.contains(UNDER_LINE)){
            // 不含下划线，仅将首字母大写
            return str.substring(0, 1).toUpperCase() + str.substring(1);
        }
        // 用下划线将原始字符串分割
        String[] camels = str.split(UNDER_LINE);
        for (String camel : camels){
            // 跳过原始字符串中开头、结尾的下换线或双重下划线
            if (camel.isEmpty()){
                continue;
            }
            // 首字母大写
            result.append(camel.substring(0, 1).toUpperCase());
            result.append(camel.substring(1).toLowerCase());
        }
        return result.toString();
    }

}
